package cn.xm.basic.service.impl;

import cn.xm.basic.constants.Constant;
import cn.xm.basic.dto.BindUserDto;
import cn.xm.basic.exception.BusinessException;
import cn.xm.basic.result.AjaxResult;
import cn.xm.basic.service.LoginService;
import cn.xm.basic.utils.HttpClientUtils;
import cn.xm.basic.utils.HttpUtil;
import cn.xm.basic.utils.MD5Utils;
import cn.xm.basic.utils.StrUtils;
import cn.xm.user.domain.Logininfo;
import cn.xm.user.domain.User;
import cn.xm.user.domain.Wxuser;
import cn.xm.user.mapper.LogininfoMapper;
import cn.xm.user.mapper.UserMapper;
import cn.xm.user.mapper.WxuserMapper;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class LoginServiceImpl implements LoginService {
    @Autowired
    private WxuserMapper wxuserMapper;
    @Autowired
    private LogininfoMapper logininfoMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserMapper userMapper;

    @Override
    public AjaxResult wechatLogin(String code) {
        code = code.split("=")[0];
        // 校验参数
        if (StringUtils.isEmpty(code)) {
            throw new BusinessException("微信code为空");
        }
        // 发送获取token请求
        // getToken含有access_token和openid
        String getToken = HttpClientUtils.httpGet(Constant.GET_TOKEN_URL
                .replace("APPID", Constant.APPID)
                .replace("SECRET", Constant.SECRET)
                .replace("CODE", code));
        // 转为json对象
        JSONObject jsonObject = JSONObject.parseObject(getToken);
        String openid = jsonObject.getString("openid");
        Wxuser wxuser = wxuserMapper.findByOpenId(openid);
        // 如果wxuser表不存在该数据就跳到绑定
        if (wxuser == null) {
            String access_token = jsonObject.getString("access_token");
            // 将access_token带上返回给前端，跳到绑定界面
            String appendParameters = "?access_token=" + access_token + "&openid=" + openid;
            return AjaxResult.me().setSuccess(false).setMessage("binder").setResultObj(appendParameters);
        }
        // 存在直接免密登录
        return loginWithoutPassword(wxuser);

    }

    private AjaxResult loginWithoutPassword(Wxuser wxuser) {
        // 存在则直接免密登录
        Logininfo logininfo = logininfoMapper.findByUserId(wxuser.getUserId());
        // 登录成功后把登录信息存返回给前端
        logininfo.setType(null);
        logininfo.setPassword(null);
        logininfo.setSalt(null);
        logininfo.setDisable(null);
        logininfo.setId(null);
        // 创建token
        String token = UUID.randomUUID().toString();
        // 将信息保存到redis
        redisTemplate.opsForValue().set(token,logininfo,30, TimeUnit.MINUTES);
        HashMap<String, Object> map = new HashMap<>();
        map.put("token",token);
        map.put("logininfo",logininfo);
        return AjaxResult.me().setResultObj(map);
    }

    @Transactional
    @Override
    public AjaxResult wechatBinder(BindUserDto bindUserDto) {
        // 参数校验
        // 校验验证码是否正确
        String smsCodeValue = (String)redisTemplate.opsForValue().get(bindUserDto.getPhone() + ":" + Constant.REGISTER_NAME);
        // 如果没有表示短信已过期或没有获取到
        if (StringUtils.isEmpty(smsCodeValue)) {
            throw new BusinessException("短信验证码不存在或已过期");
        }
        // 有则判断验证码是否正确
        String onlyValue = smsCodeValue.split(":")[0];
        if (!onlyValue.equalsIgnoreCase(bindUserDto.getVerifyCode())) {
            throw new BusinessException("短信验证码错误");
        }
        // 发送请求获取微信个人信息
        String personInfo = HttpClientUtils.httpGet(Constant.PERSON_INFO_URL
                .replace("ACCESS_TOKEN", bindUserDto.getAccessToken())
                .replace("OPENID", bindUserDto.getOpenid()));
        // 转为wxuser对象
        Wxuser wxuser = JSONObject.parseObject(personInfo, Wxuser.class);
        // 添加user
        // 查找输入的用户是否已经注册
        User user = userMapper.findByUsername(bindUserDto.getPhone());
        // 存在就直接绑定
        if (user != null) {
            wxuser.setUserId(user.getId());
            wxuserMapper.add(wxuser);
            // 添加数据后免密登录
            return loginWithoutPassword(wxuser);
        }
        // 不存在就添加user和logininfo
        Logininfo logininfo = new Logininfo();
        initLogininfo(bindUserDto, logininfo);
        logininfoMapper.add(logininfo);
        // 添加user
        user = new User();
        user.setLogininfoId(logininfo.getId());
        initUser(logininfo,user);
        userMapper.add(user);
        // 添加wxuser
        wxuser.setUserId(user.getId());
        wxuserMapper.add(wxuser);
        // 绑定成功后免密登录
        return loginWithoutPassword(wxuser);
    }

    private void initUser(Logininfo logininfo, User user) {
        BeanUtils.copyProperties(logininfo, user);
        user.setCreatetime(new Date());
        user.setState(1);
        user.setLogininfoId(logininfo.getId());
    }

    private void initLogininfo(BindUserDto bindUserDto, Logininfo logininfo) {
        logininfo.setUsername(bindUserDto.getPhone());
        logininfo.setPhone(bindUserDto.getPhone());
        String salt = StrUtils.getComplexRandomString(32);
        logininfo.setSalt(salt);
        logininfo.setDisable(true);
        String password = MD5Utils.encrypByMd5(salt + bindUserDto.getPassword());
        logininfo.setPassword(password);
        logininfo.setType(1);
    }
}
